{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Getting started with IPython\n",
    "\n",
    "----\n",
    "\n",
    "* [Goal](#Goal)\n",
    "\n",
    "\n",
    "* [Executing OS shell commands](#Executing-OS-shell-commands)\n",
    "\n",
    "\n",
    "* [Getting help with IPython](#Getting-help-with-IPython)\n",
    "\n",
    "\n",
    "* [If you remember nothing else ... ?](#If-you-remember-nothing-else-...-?)\n",
    "\n",
    "\n",
    "* [%quickref](#%quickref)\n",
    "\n",
    "\n",
    "* [The IPython magic commands](#The-IPython-magic-commands)\n",
    "\n",
    "\n",
    "* [Software introspection with IPython](#Software-introspection-with-IPython)\n",
    "\n",
    "\n",
    "----\n",
    "\n",
    "## Goal\n",
    "\n",
    "The aim of this notebook is to become familiar with some of the most important capabilities of the IPython (Interactive Python) REPL.  \n",
    "Note that term `REPL` is synonymous with `shell`:\n",
    "\n",
    ">A read–eval–print loop (REPL), also known as an interactive top level or language shell, is a simple, interactive computer programming environment that takes single user inputs (i.e. single expressions), evaluates them, and returns the result to the user.\n",
    "\n",
    "[wikipedia](https://en.wikipedia.org/wiki/Read–eval–print_loop)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Executing OS shell commands"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Probably the most common use of the IPython REPL is to execute OS shell commands directly from within a `code` cell in any  notebook.  \n",
    "\n",
    "Within any `code` cell, a command that starts with the '!' (exclamation mark also known as the \"bang\" character) is redirected to the operating system shell.  Since PYNQ runs Linux, we default to the `bash` shell.\n",
    "\n",
    "Here are some simple examples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pwd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!who"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!find -name \"*PYNQ*\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Getting help with IPython"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "IPython has many useful features. However it is not necessary to know or remember all its features.  There is a very comprehensive help system available at all times."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### If you remember nothing else ... `?`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following commands will help you find the answers to most questions that you will encounter while learning IPython.  They are also useful long after you are well acquainted with it."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Executing `?` in a code cell will pop up a window describing IPython as shown in the excerpt below:\n",
    "\n",
    "\n",
    "```\n",
    "IPython -- An enhanced Interactive Python\n",
    "=========================================\n",
    "\n",
    "IPython offers a combination of convenient shell features, special commands\n",
    "and a history mechanism for both input (command history) and output (results\n",
    "caching, similar to Mathematica). It is intended to be a fully compatible\n",
    "replacement for the standard Python interpreter, while offering vastly\n",
    "improved functionality and flexibility.\n",
    "\n",
    "At your system command line, type 'ipython -h' to see the command line\n",
    "options available. This document only describes interactive features.\n",
    "\n",
    "MAIN FEATURES\n",
    "-------------\n",
    "\n",
    "* Access to the standard Python help. As of Python 2.1, a help system is\n",
    "  available with access to object docstrings and the Python manuals. Simply\n",
    "  type 'help' (no quotes) to access it.\n",
    "\n",
    "* Magic commands: type %magic for information on the magic subsystem.\n",
    "\n",
    "* System command aliases, via the %alias command or the configuration file(s).\n",
    "...\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Try it for yourself here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `%quickref`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The %quickref command is one example of an IPython _magic function_.  IPython _magics_ are special functions that are a key part of the IPython package. Much of the power of the IPython interpreter is accessed by invoking the appropriate magics. We will see many such examples as we progress"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Executing `%quickref` in a code cell, will bring up a window summarizing all the available IPython commands.  Here is a quick excerpt:\n",
    "\n",
    "```\n",
    "IPython -- An enhanced Interactive Python - Quick Reference Card\n",
    "================================================================\n",
    "\n",
    "obj?, obj??      : Get help, or more help for object (also works as\n",
    "                   ?obj, ??obj).\n",
    "?foo.*abc*       : List names in 'foo' containing 'abc' in them.\n",
    "%magic           : Information about IPython's 'magic' % functions.\n",
    "\n",
    "Magic functions are prefixed by % or %%, and typically take their arguments\n",
    "without parentheses, quotes or even commas for convenience.  Line magics take a\n",
    "single % and cell magics are prefixed with two %%.\n",
    "\n",
    "Example magic function calls:\n",
    "\n",
    "%alias d ls -F   : 'd' is now an alias for 'ls -F'\n",
    "alias d ls -F    : Works if 'alias' not a python name\n",
    "alist = %alias   : Get list of aliases to 'alist'\n",
    "cd /usr/share    : Obvious. cd -<tab> to choose from visited dirs.\n",
    "%cd??            : See help AND source for magic %cd\n",
    "%timeit x=10     : time the 'x=10' statement with high precision.\n",
    "...\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Try it for yourself here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%quickref"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The IPython _magic_ commands"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To learn more about the IPython magics, simple type `%magic` ... Here is an excerpt from the summary of all the available IPython magic functions:\n",
    "\n",
    "```\n",
    "IPython's 'magic' functions\n",
    "===========================\n",
    "\n",
    "The magic function system provides a series of functions which allow you to\n",
    "control the behavior of IPython itself, plus a lot of system-type\n",
    "features. There are two kinds of magics, line-oriented and cell-oriented.\n",
    "\n",
    "Line magics are prefixed with the % character and work much like OS\n",
    "command-line calls: they get as an argument the rest of the line, where\n",
    "arguments are passed without parentheses or quotes.  For example, this will\n",
    "time the given statement::\n",
    "\n",
    "        %timeit range(1000)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Try it for yourself here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%magic"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To get just a list of the available magics, execute `%lsmagics`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%lsmagic"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To get more detailed information on any individual magic simply add  a '?' to either the start or the end the magic and execute it in a code cell.  \n",
    "\n",
    "For example, type either `?%pdoc` or `%pdoc?` to see the following:\n",
    "\n",
    "```\n",
    "Docstring:\n",
    "Print the docstring for an object.\n",
    "\n",
    "If the given object is a class, it will print both the class and the\n",
    "constructor docstrings.\n",
    "File:      /usr/local/lib/python3.4/dist-packages/IPython/core/magics/namespace.py\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Try it for yourself here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%pdoc?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Software introspection with IPython "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "IPython gives us more powerful help tools for any active Python object.  We can activate _software introspection_ on any object to learn more about its properties and capabilities.\n",
    "\n",
    "We demonstrate this below with the help of a short Python script that checks palindromes, strings that read the same when scanned from left-to-right as when scanned from right-to-left."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"A case-sensitive and white-space sensitive palindrome checker\"\"\" \n",
    "\n",
    "from math import floor\n",
    "\n",
    "pattern = input('Type a pattern that you want to verify is a palindrome: ')\n",
    "if pattern == (pattern[::-1]):\n",
    "    print ('\\nYes ... \"{}\"  is a palindrome'.format(pattern))\n",
    "else:\n",
    "    print ('\\nNo ... \"{}\"  is not a valid palindrome'.format(pattern))\n",
    "    length = len(pattern)\n",
    "    mid_pos = floor(length/2)\n",
    "    for i, char in enumerate(pattern):\n",
    "        i_dual = length - 1 - i\n",
    "        if i < mid_pos:\n",
    "            if pattern[i] != pattern[i_dual]:\n",
    "                print('The character \\'{}\\' in position {}  does not match the character \\'{}\\' in position {}'.\n",
    "                    format(pattern[i], i+1, pattern[i_dual], length-i))\n",
    "        else:\n",
    "            break  # All inconsistent chars on LHS and RHS identified\n",
    "            "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "IPython's _software introspection_ capabilities allow us to find out more library objects and also local objects by executing the object name followed by a `?` in  a code cell. \n",
    "\n",
    "For example, run the palindrome script with the test string 'able was i ere i saw elba' (attributed to Napoleon who was exiled to the Island of Elba after his defeat at Waterloo) and inspect these objects as follows:\n",
    "\n",
    "`pattern?`\n",
    "\n",
    "`mid_pos?`\n",
    "\n",
    "`floor?`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Try it for yourself here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pattern?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mid_pos?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "floor?"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
